#include <iostream>
#include <memory>

// shared_ptr：共享指针
// 它允许多个指针指向同一块空间
// 换句话说，这个类的拷贝构造和运算符重载没有被delete，它是可以共享的

class Test
{
public:
    Test():a(std::make_unique<int>())
    {
        std::cout << "构造函数!\n";
    }

    ~Test()
    {
        std::cout << "析构函数!\n";
    }

    void show()
    {
        std::cout << "helloworld\n";
    }

private:
    std::unique_ptr<int>a;
};


int main()
{
#if 0
    std::shared_ptr<Test> p = std::make_shared<Test>();
    p->show();
    // shared_ptr指向的内存释放的时机：直到最后一个指针也不再指向它时再释放
    // use_count：引用计数器（记录当前有多少个共享指针指向这块内存(类)）
    std::cout << p.use_count() << std::endl;
    std::shared_ptr<Test> p1 = p;
    std::cout << p.use_count() << std::endl;

    p1 = nullptr;
    std::cout << p.use_count() << std::endl;
#endif

#if 0
    // 本来用一个指针指向这块空间
    std::shared_ptr<Test> p = std::make_shared<Test>();

    // 又把它指向一块全新的空间
    p = std::make_shared<Test>();
    while(1); // 只有当p被销毁，才真正释放，while死循环的作用就是为了不让程序终止
#endif

#if 1
    // 它也有get()获取裸指针的函数
    // 但不要使用裸指针！！！
    // 该用的函数智能指针都可以用，用p->去调用，想用对象用*p去调用，都提供了相应的接口，没有必要去调裸指针！！！

    std::shared_ptr<Test> p = std::make_shared<Test>();

    // 场景1：
    // 将智能指针p拷给一个新的智能指针p1
    // 此时有两个智能指针指向这块空间
    // 引用计数器是2
    // std::shared_ptr<Test> p1(p);
    // std::cout << p.use_count() << std::endl;

    // 场景2：
    // 把p里面的裸指针拿出来给到一个新的智能指针p2，也就是说p2也指向这块空间
    // 但是它不会引起引用计数器的变化
    // 在p看来就它一个指向这块空间，在p2看来也就它一个指向这块空间
    // 引用计数器还是1
    std::shared_ptr<Test> p2(p.get());
    std::cout << p.use_count() << std::endl;

#endif

    return 0;
}